#pragma once
#include <map>
#include "CLocalObject.h"
#include "CListItem.h"
#include "CLComString.h"
#include "CLComValue.h"
#include "CLComLibrarys_global.h"
//CLCOMLIBRARYS_EXPORT

#define CLIST_INVALID_INDEX -1

typedef void(*PITEMRELEASECALLBACK)(void* pValue);

enum EMOVE_TYPE
{
	EMOVE_TYPE_UP = 0,
	EMOVE_TYPE_DOWN,

};
enum ECLIST_RETURN_VALUE
{
	ECLIST_RETURN_VALUE_FALSE = 0,
	ECLIST_RETURN_VALUE_OK,
};

class CLCOMLIBRARYS_EXPORT CLComList :
	public CLocalObject
{
public:
    CLComList();
    ~CLComList();

public:
    static void Copy(CLComList* pdst, const CLComList* psrc);

public:
	void Clear();

public:
	void SetReleaseCallback(
		PITEMRELEASECALLBACK rcb);

public:
    void InsertBack(CLComString id,
        const CLComValue& invalue,
        CLComString preID = "");

    void InsertFront(CLComString id,
        const CLComValue& invalue,
        CLComString nextID = "");

    CLComString InsertBack(
        const CLComValue& invalue,
        CLComString preID = "");

    CLComString InsertFront(
        const CLComValue& invalue,
        CLComString nextID = "");

private:
    void InsertItemBack(CLComString id,
        const CLComValue& invalue,
		CListItem* pPre = NULL);

    void InsertItemFront(CLComString id,
        const CLComValue& invalue,
		CListItem* pNext = NULL);

public:
    int MoveUp(CLComString currentid);
    int MoveDown(CLComString currentid);

    void Move2Next(CLComString frontID,
        CLComString currentid);
    void Move2Front(CLComString nextID,
        CLComString currentid);

public:
    void Move(CLComString startID,
        CLComString endID, EMOVE_TYPE moveType);

    void Move2(CLComString PosID,
        CLComString startID, CLComString endID,
		EMOVE_TYPE moveType);

public:
	void EraseItem(CListItem*& pItem);
    void EraseItem(CLComString id);
    void EraseItem(vector<CLComString>& ids);
    void EraseItem(CLComString startID, CLComString endID);

public:
    CLComString GetFirstItem()const;
    CLComString GetNextItem(CLComString id)const;
    CLComString GetPreItem(CLComString id)const;
    size_t GetSize()const;
private:
	void InsertItemBack(CListItem* pItem, CListItem* ppre);
	void InsertItemFront(CListItem* pItem, CListItem* ppre);
	void RecalIndex(CListItem* pItem);

	void DelRelateItem(CListItem* pItem);

    bool IsSerial(CLComString startID,
        CLComString endID,
		CListItem*& pStartItem,
		CListItem*& pEndItem);

    CListItem* GetItem(CLComString id)const;

	int MoveUp(CListItem* pItem);
	int MoveDown(CListItem* pItem);

	void Move2Next(CListItem* pPosItem,
		CListItem* pItem);
	void Move2Front(CListItem* pPosItem,
		CListItem* pItem);

    bool CalcSerialItems(CLComString startID,
        CLComString endID,
		CListItem*& pStartItem,
		CListItem*& pEndItem);
private:
	CListItem* m_pHeader;
	CListItem* m_pTailer;

	PITEMRELEASECALLBACK	m_pReleasecb;

    map<CLComString, CListItem*>	m_mapListItems;
	map<int, CListItem*> m_mapIndexs;
};
